using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Kopernikus.Parsing.Lexing
{
    public class LexerBuilder<TToken, TAction> where TAction : class
    {
        private readonly Dictionary<string, TAction> m_actions = new Dictionary<string, TAction>();
        private readonly Dictionary<string, TAction> m_defaultActions = new Dictionary<string, TAction>();
        private readonly Dictionary<string, TAction> m_keywordActions = new Dictionary<string, TAction>();

        public void AddIgnoreRule(string pattern)
        {
            if (string.IsNullOrEmpty(pattern))
            {
                throw new ArgumentNullException("pattern");
            }
            m_actions[pattern] = null;
        }

        public void AddDefaultRule(string literal, TAction action)
        {
            if (string.IsNullOrEmpty(literal))
            {
                throw new ArgumentOutOfRangeException("literal");
            }
            m_defaultActions[literal] = action;
        }

        public void AddDefaultSingleCharacterRule(TAction action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            m_defaultActions[string.Empty] = action;
        }

        public void AddRule(string pattern, TAction action)
        {
            if (string.IsNullOrEmpty(pattern))
            {
                throw new ArgumentOutOfRangeException("pattern");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
#pragma warning disable 168
            Regex regexValidate = new Regex(pattern);
#pragma warning restore 168
            m_actions[pattern] = action;
        }

        public void AddKeywordRule(string keyword, TAction action)
        {
            if (string.IsNullOrEmpty(keyword))
            {
                throw new ArgumentOutOfRangeException("keyword");
            }
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            m_keywordActions[keyword] = action;
        }

        public Lexer<TToken, TAction> CreateLexer()
        {
            return new Lexer<TToken, TAction>(m_actions, m_defaultActions, m_keywordActions);
        }
    }
}